package com.yaofeng.mybatis.exception;

import com.yaofeng.mybatis.common.ResponseInfo;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * 全局异常处理器
 * Created by yaofeng on 2019/8/14.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 异常捕获处理
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
   // @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseInfo exceptionHandler(HttpServletRequest request, Exception e) {
        if (e instanceof MethodArgumentNotValidException) { // JavaBean参数校验异常
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            List<ObjectError> allErrors = exception.getBindingResult().getAllErrors(); // 取出错误信息
            ObjectError error = allErrors.get(0); // 只返回第一个错误信息即可
            return ResponseInfo.fail(error.getDefaultMessage());
        } else if (e instanceof ConstraintViolationException) { // Controller方法参数校验异常
            // 错误异常
            String message = ((ConstraintViolationException) e).getConstraintViolations().iterator().next().getMessage();
            return ResponseInfo.fail(message);
        } else if (e instanceof BusinessException) {
            // 自定义业务异常
            BusinessException exception = (BusinessException) e;
            return ResponseInfo.fail(exception.getErrMsg());
        }else if(e instanceof BindException){
            // 表单验证
            // ex.getFieldError():随机返回一个对象属性的异常信息。如果要一次性返回所有对象属性异常信息，则调用ex.getAllErrors()
            FieldError fieldError = ((BindException) e).getFieldError();
            StringBuilder sb = new StringBuilder();
            sb.append(fieldError.getField()).append("=[").append(fieldError.getRejectedValue()).append("]")
                    .append(fieldError.getDefaultMessage());
            return ResponseInfo.fail(sb.toString());
        }else {
            // 系统异常，打印错误日志
            e.printStackTrace();
            return ResponseInfo.fail("系统异常，请稍后重试");
        }
    }

    /**
     * 捕获shiro中的异常信息
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = AuthorizationException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ResponseInfo handleAuthorizationException(HttpServletRequest request, AuthorizationException e) {
        return ResponseInfo.fail(e.getMessage());
    }
}
